﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Sisocana.Core;
using Sisocana.Core.Models;
using Sisocana.Core.Interfaces;
using Sisocana.Dal.EntityModels;
using Sisocana.Dal;
using Sisocana.Dal.Interfaces;
using System.Data;
using System.Configuration;


namespace Sisocana.Core
{
    public class SiteService : ServiceBase<ISiteModel>, ISiteService
    {
        public SiteService()
            : this(new SiteRepository(), new UsuarioRepository(), new CSSCatRepository(),new MasterPageCatRepository(), new LocalidadRepository())
        {
        }

        private ISiteRepository _siteRepository;
        private IUsuarioRepository userRepo;
        private ICSSCatRepository _cssRepository;
        private IMasterPageCatRepository _MasterRepository;
        private ILocalidadRepository localidadRepo;

        public SiteService(ISiteRepository siteRepository, IUsuarioRepository usuarioRepository, ICSSCatRepository cssRepo, IMasterPageCatRepository masterRepo, ILocalidadRepository localRepo)
        {
            _siteRepository = siteRepository ?? new SiteRepository();
            userRepo = usuarioRepository ?? new UsuarioRepository();
            _cssRepository = cssRepo ?? new CSSCatRepository();
            _MasterRepository = masterRepo ?? new MasterPageCatRepository();
            localidadRepo = localRepo ?? new LocalidadRepository();
        }

        public void createSitioMapperEF2Model()
        {
            AutoMapper.Mapper.CreateMap<Sitio, SiteModel>()
                .ForMember(s => s.name_css, opt => opt.MapFrom(c => c.CSSCat.nombreCSS))
                .ForMember(s => s.name_master, opt => opt.MapFrom(c => c.MasterPageCat.nombreMaster))
                .ForMember(dest => dest.logo, opt => opt.MapFrom(src => src.imgLogo.imgByte))
                .ForMember(dest => dest.logoNomb, opt => opt.MapFrom(src => src.imgLogo.imgNombre))
                .ForMember(dest => dest.logoExt, opt => opt.MapFrom(src => src.imgLogo.imgExt));
         }

        public void createSitioMapperModel2EF()
        {
            AutoMapper.Mapper.CreateMap<SiteModel, Sitio>();
        }

        public SiteModel Get(int id)
        {
            createSitioMapperEF2Model();
            Sitio sitioEF = _siteRepository.GetSingle(s => s.id == id);
            SiteModel sitio = new SiteModel();
            sitio = AutoMapper.Mapper.Map(sitioEF, sitio);
            return sitio;
        }

        private void addAdminIfValid(string userName, Sitio site)
        {
            Usuario usuario = userRepo.GetSingle(u => u.nombreUsuario == userName);
            if (!site.Usuario.Contains<Usuario>(usuario) && !usuario.Sitio.Contains<Sitio>(site))
            {
                site.Usuario.Add(usuario);
                usuario.Sitio.Add(site);
            }
        }

        public void saveExistingSite(bool isGeneralAdmin, SiteModel sitioView, String[] selectedUsers)
        {            
            createSitioMapperModel2EF();
            Sitio SitioEF = _siteRepository.GetSingle(s => s.id == sitioView.id);
            SitioEF = AutoMapper.Mapper.Map(sitioView, SitioEF);
            if (selectedUsers == null)
                selectedUsers = new String[0];

            if (isGeneralAdmin)
            {
                List<String> alreadyAdmin = new List<String>();
                List<String> adminNoMore = new List<String>();
                foreach (var admin in SitioEF.Usuario)
                    if (selectedUsers.Contains(admin.nombreUsuario))
                        alreadyAdmin.Add(admin.nombreUsuario);
                    else
                        adminNoMore.Add(admin.nombreUsuario);

                foreach (var adminName in adminNoMore)
	            {
                    Usuario user = userRepo.GetSingle(u => u.nombreUsuario == adminName);
                    SitioEF.Usuario.Remove(user);
                    if (user.Sitio.Contains(SitioEF))
                        user.Sitio.Remove(SitioEF);
	            }

                IEnumerable<String> newAdmins = selectedUsers.Where(s => !alreadyAdmin.Contains(s));
                foreach (var userName in newAdmins)
                    addAdminIfValid(userName, SitioEF);
            }
            else
            {
                foreach (var userName in selectedUsers)
                    addAdminIfValid(userName, SitioEF);
            }
            _siteRepository.Save();
        }

        public int saveConfVisual(SiteModel sitioView)
        {

                 
         
          Sitio sitEF = _siteRepository.GetSingle(s => s.id == sitioView.id);
          CSSCat cssCat = _cssRepository.GetSingle(c => c.nombreCSS.Trim() == sitioView.name_css.Trim());
          MasterPageCat masterCat = _MasterRepository.GetSingle(c => c.nombreMaster.Trim() == sitioView.name_master.Trim());          

          sitEF.MasterPageCat = masterCat;
          sitEF.CSSCat = cssCat;

          if (sitioView.logoNomb != null)
          {
              sitEF.imgLogo.imgByte = sitioView.logo;
              sitEF.imgLogo.imgExt = sitioView.logoExt;
              sitEF.imgLogo.imgNombre = sitioView.logoNomb;
          }
        try{
          _siteRepository.Save();
          return 0;
        }
        catch (Exception e){
            return e.InnerException.GetHashCode();
        }
    }

        public int createSite(SiteModel sitioView, String[] selectedUsers)
        {
            // Seteo parametros que no se hacen desde la vista
            sitioView.estado = "M";
            sitioView.fecha = (System.DateTime)sitioView.fecha;

            // Hago el mapeo a la entidad para persistir
            createSitioMapperModel2EF();

            // Para que funcione el mapper tengo que crearlo vacio antes.
            Sitio SitioEF = new Sitio();
            SitioEF = AutoMapper.Mapper.Map(sitioView, SitioEF);

            // Creo los repositorios auxiliares
            CSSCatRepository cssS = new CSSCatRepository();
            MasterPageCatRepository masterS = new MasterPageCatRepository();

            string masterName = ConfigurationManager.AppSettings["DefaultMasterName"];
            // Busco la Master y sino la catalogo, esta por defecto, hay que ver que se hace luego al final.
            MasterPageCat master = masterS.GetSingle(a => a.nombreMaster == masterName);
            if (master == null)
            {
                //Si no existe la creo
                master = new MasterPageCat();
                master.nombreMaster = masterName;
                master.descripcion = ConfigurationManager.AppSettings["DefaultMasterDescription"];
                master.path = ConfigurationManager.AppSettings["DefaultMasterPath"];
                master.Sitio.Add(SitioEF);
                masterS.Add(master);
            }
            SitioEF.MasterPageCat = master;

            string cssName = ConfigurationManager.AppSettings["DefaultCSSName"];
            // Busco el CSS y sino lo catalogo, este esta por defecto, hay que ver que se hace luego al final.
            CSSCat css = cssS.GetSingle(b => b.nombreCSS == cssName);
            if (css == null)
            {
                css = new CSSCat();
                css.nombreCSS = cssName;
                css.descripcion = ConfigurationManager.AppSettings["DefaultCSSDescription"];
                css.path = ConfigurationManager.AppSettings["DefaultCSSPath"];
                css.Sitio.Add(SitioEF);
                cssS.Add(css);
                css.MasterPageCat = master;
                //Aca supongo que si no existe la master tampoco existe el css, entonces creo la relacion acorde.
                master.CSSCat.Add(css);
            }
            SitioEF.CSSCat = css;

            UsuarioRepository us = new UsuarioRepository();
            if (selectedUsers != null)
            {
                //Agrego Usuarios seleccionados.
                foreach (var nombre in selectedUsers)
                {
                    Usuario usuario = us.GetSingle(u => u.nombreUsuario == nombre);
                    usuario.Sitio.Add(SitioEF);
                    SitioEF.Usuario.Add(usuario);
                }
            }

            _siteRepository.Add(SitioEF);

            try
            {
                _siteRepository.Save();
                return 0;
            }
            catch (Exception e)
            {
                return e.InnerException.GetHashCode();
            }

        }

        #region AA

        public List<AffectedAreaMarker> getAreasAfectadas(int idSitio)
        {
            Sitio sitio = _siteRepository.GetSingle(s => s.id == idSitio);
            var areasAfectadas = new List<AffectedAreaMarker>();
            foreach (var localidad in sitio.AreasAfectadas)
            {
                areasAfectadas.Add(new AffectedAreaMarker(localidad));
            }
            return areasAfectadas;
        }

        public string agregarAreasAfectadas(int idSitio, IEnumerable<AffectedAreaMarker> areasNuevas)
        {
            StringBuilder sb = new StringBuilder();
            Sitio sitio = _siteRepository.GetSingle(s => s.id == idSitio);
            foreach (var areaNueva in areasNuevas)
                try
                {
                    sitio.AreasAfectadas.Add(areaNueva.ToLocalidad(sitio));
                    sb.AppendLine(String.Format("El área {0} se agregó con éxito", areaNueva.AreaName));
                }
                catch (Exception e)
                {
                    sb.AppendLine(String.Format("El area {0} no pudo ser agregada: {1}", areaNueva.AreaName, e.Message));
                }
            if (sb.Length > 0)
                _siteRepository.Save();
            return sb.ToString();
        }

        public string eliminarAreasAfectadas(int idSitio, IEnumerable<AffectedAreaMarker> areasEliminadas)
        {
            StringBuilder sb = new StringBuilder();
            Sitio sitio = _siteRepository.GetSingle(s => s.id == idSitio);
            foreach (var areaEliminada in areasEliminadas)
                try
                {
                    Localidad localidad = localidadRepo.GetSingle(l => l.id == areaEliminada.AreaId);
                    sitio.AreasAfectadas.Remove(localidad);
                    localidadRepo.Delete(localidad);
                    sb.AppendLine(String.Format("El área {0} se eliminó con éxito", areaEliminada.AreaName));
                }
                catch (Exception e)
                {
                    sb.AppendLine(String.Format("El area {0} no pudo ser eliminada: {1}", areaEliminada.AreaId, e.Message));
                }
            if(sb.Length > 0)
                _siteRepository.Save();
            return sb.ToString();
        }

        public string actualizarAreasAfectadas(int idSitio, IEnumerable<AffectedAreaMarker> areasModificadas)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var areaModificada in areasModificadas)
                try
                {
                    Localidad localidad = localidadRepo.GetSingle(l => l.id == areaModificada.AreaId);
                    localidad.latitud = areaModificada.Latitude;
                    localidad.longitud = areaModificada.Longitude;
                    sb.AppendLine(String.Format("El área {0} se actualizó con éxito", areaModificada.AreaName));
                }
                catch (Exception e)
                {
                    sb.AppendLine(String.Format("El area {0} no pudo ser eliminada: {1}", areaModificada.AreaId, e.Message));
                }
            if (sb.Length > 0)
                localidadRepo.Save();
            return sb.ToString();
        }

        #endregion

        public string getMasterPath(int id)
        {
            Sitio sitio = _siteRepository.GetSingle(s => s.id == id);
            return sitio.MasterPageCat.path;
        }

        public string getCssPath(int id)
        {
            Sitio sitio = _siteRepository.GetSingle(s => s.id == id);
            return sitio.CSSCat.path;
        }

        public int changeState(int id, string state)
        {
            Sitio sitio = _siteRepository.GetSingle(s => s.id == id);
            if (sitio == null)
                return -2;
            else
            {
                switch (state)
                {
                    case "Inactive":
                        sitio.estado = "I";
                        break;
                    case "Maintence":
                        sitio.estado = "M";
                        break;
                    case "On Line":
                        sitio.estado = "O";
                        break;
                    default:
                        return -1;
                }
                try
                {
                    _siteRepository.Save();
                    return 0;
                }
                catch (Exception e)
                {
                    return e.InnerException.GetHashCode();
                }
            }

        }

         public SiteModel GetSingle(Expression<Func<SiteModel, bool>> whereCondition)
        {
            createSitioMapperEF2Model();

            IList<Sitio> sitiosEF = _siteRepository.GetAll();
            List<SiteModel> sitios = new List<SiteModel>();

            sitios = AutoMapper.Mapper.Map(sitiosEF, sitios);

            IQueryable<SiteModel> sitioRet = sitios.AsQueryable<SiteModel>().Where(whereCondition);

            List<SiteModel> ret = sitioRet.ToList();
            
             if (ret.Count == 0)
                return null;

            return ret.First();
        }

        public void Add(SiteModel entity)
        {
            throw new NotImplementedException();
        }

        public void Delete(SiteModel entity)
        {
            throw new NotImplementedException();
        }

        public void Update(SiteModel entity)
        {
            throw new NotImplementedException();
        }

        public IList<SiteModel> GetAll(Expression<Func<SiteModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        public IList<SiteModel> GetAll()
        {
            createSitioMapperEF2Model();

            IList<Sitio> sitiosEF = _siteRepository.GetAll();
            List<SiteModel> sitios = new List<SiteModel>();
            foreach (Sitio sitEF in sitiosEF)
            {
                SiteModel sit = new SiteModel();
                sit = AutoMapper.Mapper.Map(sitEF, sit);
                sitios.Add(sit);
            }
            return sitios;
        }

        public IQueryable<SiteModel> Query(Expression<Func<SiteModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        public long Count(Expression<Func<SiteModel, bool>> whereCondition)
        {
            throw new NotImplementedException();
        }

        public long Count()
        {
            throw new NotImplementedException();
        }

        /*Usar esto para completar el mapeo de las propiedades que son imposible mapear con el 
         * mapper , agregar aca los "mapeadores" manuales*/
        SiteModel ISiteService.mapperCompleter(SiteModel sit)
        {

            /*completo la lista de redes*/
            RedSocialAsociadoService rep = new RedSocialAsociadoService();
            IList<RedSocialAsociadoModel> lredes = rep.GetAll(r => r.idSitio == sit.id);
            sit.redesSociales = lredes;

            RedSocialAsociadoModel rs = rep.GetSingle(r=> ((r.RedesSocialesName.Trim() == "Twitter") && (r.idSitio == sit.id) ));

            if (rs != null)
            {
                sit.tweetsearch = rs.tagBusqueda;
                sit.tweetuser = rs.tagUser;
                sit.tweetCant = rs.cantVisualizar;
                sit.bsColor = rs.BackgroundShellColor;
                sit.btColor = rs.BackgroundTweetsColor;
                sit.sColor = rs.ShellColor;
                sit.tColor = rs.TweetsColor;
                sit.theigth = rs.heigth;
                sit.twidth = rs.width;
            }
            else
            {
                sit.tweetsearch = "";
                sit.tweetuser = "";
                sit.tweetCant = 0;
                sit.bsColor = "";
                sit.btColor = "";
                sit.sColor = "";
                sit.tColor = "";
                sit.theigth = 0;
                sit.twidth = 0;
            }

            rs = rep.GetSingle(r => ((r.RedesSocialesName.Trim() == "Facebook") && (r.idSitio == sit.id)));

            if (rs != null)
            {
                sit.faceuser = rs.tagUser;
            }
            else
            {
                sit.faceuser = "";
            }

            // Video
            VideoAsociadoRepository repVideo = new VideoAsociadoRepository();
            VideoAsociado video = repVideo.GetSingle(vid => vid.Sitio.id == sit.id);
            if (video != null)
            {
                sit.videoKey = video.apiKey;
                sit.videoTag = video.tagBusqueda;
                sit.videoSize = video.cantVisualizar;
                sit.videoHeigth = video.heigth;
                sit.videoTipo = video.tipo;
                sit.videoWidth = video.width;
            }
            else
            {
                sit.videoKey = "";
                sit.videoTag = "";
                sit.videoSize = 0;
                sit.videoHeigth = 0;
                sit.videoTipo = "";
                sit.videoWidth = 0;
            }

            //Imagen
            ImagenAsociadoRepository repImagen = new ImagenAsociadoRepository();
            ImagenAsociado imagen = repImagen.GetSingle(vid => vid.Sitio.id == sit.id);
            if (imagen != null)
            {
                sit.imageCant = imagen.cantVisualizar;
                sit.imagekey = imagen.apiKey;
                sit.imageSecret = imagen.appSecret;
                sit.imageTag = imagen.tagBusqueda;
                sit.imageWidth = imagen.width;
                sit.imageHeigth = imagen.heigth;
                sit.imageColor = imagen.autWindows;
                sit.imageGallery = imagen.photoSetId;
            }
            else
            {
                sit.imageCant = 0;
                sit.imagekey = "";
                sit.imageSecret = "";
                sit.imageTag = "";
                sit.imageWidth = 0;
                sit.imageHeigth = 0;
                sit.imageColor = "";
                sit.imageGallery = "";
            }

            //NOTICIAS
            NoticiaAsociadoService noticiasService = new NoticiaAsociadoService();
            IList<NoticiaAsociadaModel> sources = noticiasService.GetAll(r => r.idSitio == sit.id);
            sit.sources = sources;


            return sit;

        }





        public int setEstado(string estado, int idSitio)
        {
            Sitio sitio = _siteRepository.GetSingle(s => s.id == idSitio);
            sitio.estado = estado;

           try
            {
                _siteRepository.Save();
                return 0;
            }
            catch (Exception e)
            {
                return e.InnerException.GetHashCode();
            }

        }

        
        string ISiteService.getEstado(int idSitio)
        {

            Sitio sitio = _siteRepository.GetSingle(s => s.id == idSitio);
            return sitio.estado;
        }


        public IList<SiteModel> getAllVUser(string user)
        {
            createSitioMapperEF2Model();

            IList<Sitio> sitiosEF = _siteRepository.GetAll();

            List<SiteModel> sitios = new List<SiteModel>();
            foreach (Sitio sitEF in sitiosEF)
            {
                Boolean esta = false;
                foreach (Usuario us in sitEF.Usuario)
                {
                    if (us.nombreUsuario.Trim()==user.Trim()) {
                        esta=true;
                        break;
                    }
                }
                
                if (esta)
                {
                    SiteModel sit = new SiteModel();
                    sit = AutoMapper.Mapper.Map(sitEF, sit);
                    sitios.Add(sit);
                }
            }
            return sitios;
        }
    }
}
